import abc
from datetime import date
from typing import List

from pywebio import output, pin

from emi.report.data import LogData
from emi.report.storage import LogDataDB
from emiui import UISession


class LogDataView():

    """
    与DataListView不同，这里是包含排序功能的。
    """
    def __init__(self,
                 log_db:LogDataDB,
                 name: str = "",
                 view_height = 800,
                 ):
        self.log_db = log_db
        self.PREFIX = f"{name}_ldv"
        self.ui_session = None
        self._view_height = view_height
        self._cur_tags = None

        self._count_options = [
            {"label": "500个","value": 500,"selected":True},
            {"label": "1000个", "value": 1000, "selected": False},
            {"label": "5000个", "value": 5000, "selected": False},
        ]


    @abc.abstractmethod
    def get_item_view(self,offset:int,is_head:bool,log:LogData):
        """
        获取列表元素。
        :param offset:  序号
        :param is_head:  是否列表头部
        :param data:
        :return:
        """
        if is_head:
            return ["时间","类型","标签","信息","错误信息"]
        else:
            sub_type = log.level
            if sub_type == 100:
                type_name = "调试"
            elif sub_type == 200:
                type_name = "信息"
            elif sub_type == 300:
                type_name = "告警"
            elif sub_type == 400:
                type_name = "错误"
            else:
                raise Exception()
            return [log.time.strftime('%Y-%m-%d %H:%M:%S'),
                    type_name,
                    log.tag,
                    log.msg,
                    ""
                    ]

    def get_selected_value(self,options:List):
        for count_option in options:
            if count_option['selected']:
                return count_option['value']
        return None

    async def _on_count_option_chagned(self,count):
        for count_option in self._count_options:
            if count_option['value'] == count:
                count_option['selected'] = True
            else:
                count_option['selected'] = False
        await self._refresh_content()


    async def show(self):
        if self.ui_session is None:
            self.ui_session = UISession.get()
        output.put_scrollable([
            output.put_scope(name=f"{self.PREFIX}_main")
        ],height = self._view_height)
        await self._refresh()


    async def _refresh(self):
        day_list = self.log_db.get_day_list()

        if len(day_list) < 1:
            with output.use_scope(name=f"{self.PREFIX}_main", clear=True):
                output.put_text("没有日志内容")
            return

        day_options = []
        day_options.append({"label":"全部","value":-1,"selected":True})
        for day in reversed(day_list):
            day_options.append({"label":f"{day}","value":day.toordinal()})

        tag_list = self.log_db.get_tag_list()
        tag_options = []
        #tag_options.append({"label": f"全部", "value": None,"selected":True})
        for tag in list(tag_list):
            if len(tag) > 0:
                tag_options.append({"label": f"{tag}", "value": tag})
            else:
                tag_options.append({"label": f"其它", "value": ""})


        with output.use_scope(name=f"{self.PREFIX}_main", clear=True):
            row_items = []
            size_desc = ""

            ## 显示时间。
            row_items.append(
                pin.put_select(f"{self.PREFIX}_op_day", options=day_options, help_text="选择日期").style(
                    "margin-right:10px"))
            pin.pin_on_change(f"{self.PREFIX}_op_day", onchange=self._refresh_content, clear=True)
            size_desc += "100px "

            ## 显示个数选项。
            row_items.append(
                pin.put_select(f"{self.PREFIX}_op_count", options=self._count_options, help_text="显示个数").style(
                    "margin-right:10px"))
            pin.pin_on_change(f"{self.PREFIX}_op_count", onchange=self._on_count_option_chagned, clear=True)
            size_desc += "100px "

            ### 显示Ta过滤器
            row_items.append(
                pin.put_select(f"{self.PREFIX}_op_tag", options=tag_options, help_text="标签",multiple=True).style(
                    "margin-right:10px"))
            pin.pin_on_change(f"{self.PREFIX}_op_tag", onchange=self._refresh_content, clear=True)
            size_desc += "100px "

            row_items.append(output.put_button(label="刷新", onclick=self._refresh_content, small=True).style("margin-top:3px"))
            size_desc += '70px'
            output.put_row(row_items, size=size_desc)

            output.put_scope(f"{self.PREFIX}_content")
        await self._refresh_content()


    async def _refresh_content(self,null_args=None):
        day_order = await pin.pin[f"{self.PREFIX}_op_day"]
        tags = await pin.pin[f"{self.PREFIX}_op_tag"]

        if None in tags:
            tags = None

        _day = None if day_order < 0 else date.fromordinal(day_order)
        _count:int = self.get_selected_value(self._count_options)
        data_list = self.log_db.get_newest_logs(count=_count,day=_day,tags=tags)
        with output.use_scope(f"{self.PREFIX}_content", clear=True):
            table_data = []
            table_data.append(self.get_item_view(0, is_head=True, log=None))
            for index, data in enumerate(data_list):
                cell_list = self.get_item_view(index+1, is_head=False, log=data)
                if isinstance(cell_list[0], list):
                    table_data.extend(cell_list)
                else:
                    table_data.append(cell_list)
            output.put_table(table_data)

